Iteration X 3D Graphics Engine and projects.
Copyright  2015 Max "Shrinker" Wieden.
All rights reserved.

Standard engine controls (for 3D projects)
------------------------------------------
Esc: toggly fly mode
F1: reset camera
F2: true fullscreen
F3: fake fullscreen (use when F2 does not yield the desired results, e.g. when screenshots yield blackness or when other programs are obstructed)
F4: set FPS (default: screen refresh rate minus one)

Controls with fly mode enabled:
	WASD/arrow keys: move around
	Mouse wheel/+ and -: double or halve movement speed
	Ctrl/Shift/C: move down
	Space/Num0: move up

Controls with fly mode disabled:
	WASD/arrow keys: move the mouse cursor by one pixel in the respective direction


ATI and NVIDIA workarounds (for 3D projects)
--------------------------------------------
Unfortunately, both ATI and NVIDIA deviate from the OpenGL standard in some ways.
At the time of writing, especially ATI's drivers are full of bugs that require major workarounds to get shaders working. You might like their graphics cards for being very affordable, but over the years I have come to hate them with passion, for deviating from the official OpenGL specification in countless ways. And their new "Mantle" API turns out to be nothing but a marketing trick which is in reality a huge step backwards in terms of international standardization, proper abstraction and API design. I wish nothing good for that company. The only good they do for me is help me figure out where the NVIDIA driver was too lenient and forgiving in terms of uninitialized data.

If you have an NVIDIA card, please run "configure for NVIDIA cards.bat" once.
If you have an ATI/AMD card, please run "configure for ATI-AMD graphics.bat" once.

This is a list of problems I have to work around. All of these behaviors are not backed by the official OpenGL specification and are therefore to be considered bugs in the drivers.
	ATI - vertex attribute location 0
		Description: If nothing is bound to attribute location 0, nothing is drawn at all.
		Use: Rendering geometry without anything bound to a vertex attribute, but with all vertex positions inferred from gl_VertexID
		Workaround: At the cost of unnecessarily wasted resources, feed in gl_VertexID through an attribute at location 0.

	ATI - built-ins failing because of their names
		Description: If an input variable name is used that appears before a built-in when sorted strictly according to the ANSI character code order, the built-in fails. For instance, using an input variable named "LightColor" renders gl_VertexID broken because 'g' comes after 'L'.
		Use: General use
		Workaround: Prefixing all inputs with '_' seemed to work for some reason.

	ATI - uniform blocks failing after loading a shader from cache
		Description: Uniform buffers used in conjunction with a loaded shader binary from cache exhibit all properties they should in the data, but someting in the driver seemingly causes an std140 layout annotation to be ignored, making them unaddressable from the program.
		Use: General use
		Workaround: Uniform blocks can not be used in conjunction with the shader cache. Where uniform blocks are a necessity, the cache can't be used and the shaders in question must be recompiled every time, which slows the program down. If uniform blocks without the std140 alignment information had to be used from this erroneous cache loading process, it would not be possible to associate them with uniform buffer objects and update the model and view matrices at the same time properly, leading to worse rendering performance with multiple active shaders.

	ATI - atan functions yielding garbage
		Description: The atan functions yield proper values only for certain ranges of angles, and seemingly apply an offset in the x direction before calculating the angles for other values.
		Use: General use, especially for finding angles
		Workaround: float a; if (d.y >= 0 && (d.y <= d.x || d.y <= -d.x) || d.y <= 0 && (-d.y <= d.x || -d.y <= -d.x)) a = atan(d.x, -d.y)-Pi/2; else a = atan(d.y, d.x);

	ATI - control flow fuck-up
		Description: In some cases, a conditional return statement inside of GLSL code seems to confuse the runtime of the ATI driver so much that it's not merely having prediction errors causing reduced performance, but even goes so far that the code is not run right, and an else branch is discarded entirely.
		Use: General use, everywhere in code
		Workaround: Rewrite the shader code to make less sense.

	NVIDIA - const qualifier
		Description: For the statement "const float x = sin(1);", const is not allowed by NVIDIA, but it is backed by the GLSL specification, which clearly states that a const expression may have a built-in function that is parametrized with const-eligible expressions. Not declaring an expression that is used as const as const has drawbacks on code-self documentation and can have drawbacks on shader optimization.
		Use: General use
		Workaround: Omit the const qualifier.


Windows workarounds
-------------------
There appears to be a bug in the mechanism handling the SetCursorPos function.
I use this function to center the mouse to the window center when entering the fly mode, and then to keep it there and only use the mouse position deltas when looking around.
Sometimes, though, Windows would send a ghost mouse move message to the program, coming from the position where the cursor was before calling this function. This caused the camera to jerk around every now and then, especially when moving the mouse while entering the fly mode.
The same effect would sometimes also catch the mouse in the center position and not put it back when leaving the fly mode.
My workaround is to let the whole main program thread sleep for ~5ms when entering or leaving the fly mode.
Unfortunately, this doesn't mitigate the bug while turning the camera around: It can jerk a little bit every now and then because of this bug.
One alternative for me would be to use the RAWMOUSE Windows API raw input mechanism, but I'd have a hard time recreating the mouse acceleration settings configured for the computer, as those "mouse pointer ballistics" are not part of that mechanism.
Because of this, very rarely, the camera can still make an unexpected turn, or the mouse can be at the window center when leaving the fly mode.
References:
	http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/bdafc3b3-c42b-40d0-9cbe-ec7152e3f896/setcursorpos-and-wmmousemove (visited 2014-02-27)
	http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/f3f8cd2e-599b-4b94-a461-4fa50ad1a3dc/bug-with-the-global-mouse-hook (visited 2014-02-27)
	http://www.rohitab.com/discuss/topic/36141-setcursorpos-problem/ (visited 2014-02-27)

Something is weird in the way Windows handles messages of modal dialog boxes:
In the following situation, a key released event should be queued, okay, but it should not be processed on the spot.
But it gets processed on the spot, in the main thread... which is really, really weird.
1. create a modal text display box using DialogBoxIndirectParam and its own message queue override
2. in the code, right after the text display box, bring up a modal file dialog using GetOpenFileName with an OPENFILENAME struct
3. close the text display box by pressing down Esc -- the release of Esc is queued somewhere else because the box is closed
4. the WM_SYSKEYUP event for releasing Esc actually lands in the main message queue, despite that very message queue already being busy running the code controlling the dialog boxes...
I can understand that such a key released event is generated and sent someplace else, because pressing Esc down already closes the dialog... but it happens that this key up event is processed right on the spot, in the main message queue, instead of being queued to the end of that.
And I've confirmed that this happens in the same thread where the main message queue already is, but somewhere entirely else, processing code.
My workaround is a status variable checking if I'm already in a key handler (or another such handler, for good measure), basically acting as a semaphore within the same thread.
I deem this a bug and think that this behavior indicates that Windows messed up which thread is in charge of the main message loop at that point, juggling program counters and stack pointers around for the text display dialog or the file selection dialog.


Reload semantics (for projects that use them)
---------------------------------------------
A file is loaded or reloaded when it is dropped onto the program window, when it is specified through the command line on startup, and when it is changed.


Error codes for my command-line programs
----------------------------------------
	0: normal termination
	1: program showed expected command-line arguments and terminated (no args were supplied)
	2: termination with exception (red text in command-line)


How to set up your command-line properly
----------------------------------------
In order to set up your command-line properly for use with my programs, I recommend that you do the following things:
* Hit Windowskey+R to bring up the run dialog
* type cmd and hit return
* rightclick on the title bar of that window and select "Defaults"
* Tab "Options"
	* set the command history buffer size and number of buffers to the maximum (999)
	* enable "QuickEdit Mode" - this allows you to simply click and drag to select text (hit return to copy selected text)
	* enable "Insert Mode" - this allows you to insert text with a rightclick
* Tab "Layout"
	* set the Screen Buffer Size Height to 999 so that you can scroll up vertically and will not miss anything important
